package com.whfc.ms.config;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author: sun
 * @version: v1.0.0
 */
@Configuration
public class CustomCookieSerializer implements CookieSerializer {

    private static final Log logger = LogFactory.getLog(CustomCookieSerializer.class);

    public final static String HEADER_TOKEN_KEY = "Authorization";
    private String jvmRoute = null;
    private boolean useBase64Encoding = true;

    @Override
    public List<String> readCookieValues(HttpServletRequest request) {
        String str = request.getHeader(HEADER_TOKEN_KEY);
        List<String> matchingCookieValues = new ArrayList<>();
        if (!StringUtils.isEmpty(str)) {
            String sessionId = (this.useBase64Encoding ? base64Decode(str) : str);
            if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
                sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
            }
            matchingCookieValues.add(sessionId);
        }
        return matchingCookieValues;
    }

    @Override
    public void writeCookieValue(CookieValue cookieValue) {
        HttpServletResponse response = cookieValue.getResponse();
        String value = getValue(cookieValue);
        response.addHeader(HEADER_TOKEN_KEY, value);
    }

    private String base64Decode(String base64Value) {
        try {
            byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
            return new String(decodedCookieBytes);
        } catch (Exception ex) {
            logger.debug("Unable to Base64 decode value: " + base64Value);
            return null;
        }
    }

    private String base64Encode(String value) {
        byte[] encodedCookieBytes = Base64.getEncoder().encode(value.getBytes());
        return new String(encodedCookieBytes);
    }

    private String getValue(CookieValue cookieValue) {
        String requestedCookieValue = cookieValue.getCookieValue();
        String actualCookieValue = requestedCookieValue;
        if (this.jvmRoute != null) {
            actualCookieValue = requestedCookieValue + this.jvmRoute;
        }
        if (this.useBase64Encoding) {
            actualCookieValue = base64Encode(actualCookieValue);
        }
        return actualCookieValue;
    }

}
